import os
import hashlib
import codecs
import datetime

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.utils.html import format_html

from .validators import validate_file_extension


FILE_PATH = os.path.join(settings.MEDIA_ROOT, "certfiles/")


# Create your models here.
class ClientInfo(models.Model):
    NORMAL = 0
    BLOCKED = 1
    DELETE = 2

    CLIENT_STATUS = [
        (NORMAL, "正常"),
        (BLOCKED, "禁用"),
        (DELETE, "删除")
    ]

    name = models.CharField(max_length=128, verbose_name="客户名称")
    status = models.PositiveSmallIntegerField(choices=CLIENT_STATUS, default=NORMAL, verbose_name="用户状态")
    contact = models.CharField(max_length=11, blank=True, null=True, verbose_name="联系方式")
    region = models.CharField(max_length=255, blank=True, null=True, verbose_name="地址")

    add_time = models.DateTimeField(auto_now_add=True, verbose_name="记录添加时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="记录修改时间")

    seller = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="clients",
                               verbose_name="销售人员")

    def colored_status(self):
        if self.status == self.DELETE:
            color_code = 'red'
        elif self.status == self.BLOCKED:
            color_code == 'darkgray'
        else:
            color_code = 'green'

        return format_html(
            '<span style="color: {};">{}</span>',
            color_code,
            self.get_status_display()
        )

    colored_status.short_description = "用户状态"

    def __str__(self):
        return self.name

    def __repr__(self):
        return self.name

    class Meta:
        ordering = ["-add_time"]
        verbose_name = verbose_name_plural = "用户信息"


class DeviceTypeInfo(models.Model):
    type_name = models.CharField(max_length=40, blank=False, null=False, unique=True, verbose_name="设备类型")

    add_time = models.DateTimeField(auto_now_add=True, verbose_name="记录添加时间")

    def __str__(self):
        return self.type_name

    def __repr__(self):
        return self.type_name

    class Meta:
        ordering = ["-add_time"]
        verbose_name = verbose_name_plural = "设备类型"


class DeviceInfo(models.Model):
    device_id = models.CharField(max_length=40, blank=True, null=True, unique=True, verbose_name="设备唯一识别码")
    device_cpu = models.CharField(max_length=128, blank=True, null=True, verbose_name="CPU 型号信息")
    device_mac = models.CharField(max_length=64, blank=True, null=True, verbose_name="MAC 地址")
    device_board = models.CharField(max_length=128, blank=True, null=True, verbose_name="主板信息")
    device_mid = models.CharField(max_length=32, blank=True, null=True, verbose_name="机器识别码")
    is_banned = models.BooleanField(default=False, verbose_name="设备是否注销")

    add_time = models.DateTimeField(auto_now_add=True, verbose_name="记录添加时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="记录修改时间")

    type = models.ForeignKey("DeviceTypeInfo", on_delete=models.DO_NOTHING, related_name="device_infos", verbose_name="设备类型")
    client = models.ForeignKey("ClientInfo", on_delete=models.DO_NOTHING, related_name="devices", verbose_name="客户")

    def get_device_id(self):
        if not (self.device_cpu and self.device_mac and self.device_board and self.device_mid):
            return None

        client_identity = ":".join(
            [self.client.name, self.device_cpu, self.device_mac, self.device_board, self.device_mid])
        h = hashlib.new("ripemd160")
        h.update(codecs.encode(client_identity))
        return h.hexdigest()

    def save(self, *args, **kwargs):
        self.device_id = self.get_device_id()
        super().save(*args, **kwargs)

    def __str__(self):
        return f"设备 {self.id}:{self.client}"

    def __repr__(self):
        return f"设备 {self.id}:{self.client}"

    class Meta:
        ordering = ["-add_time"]
        verbose_name = verbose_name_plural = "设备信息"


def cert_file_name(instance, filename):
    time = datetime.datetime.now().strftime("%Y_%m_%d")
    ext = os.path.splitext(filename)[1]

    try:
        comp_name = instance.device.client.name
        device_id = instance.device.id
    except Exception as e:
        comp_name = "Unknown"
        device_id = 0

    new_filename = "{}_{}_{}_authfile.{}".format(device_id, comp_name, time, ext)

    return os.path.join(FILE_PATH, new_filename)


class CertificationInfo(models.Model):
    value = models.CharField(max_length=512, blank=True, null=True, unique=True, verbose_name="激活码")
    start_time = models.DateField(null=True, blank=True, verbose_name="起始时间")
    end_time = models.DateField(null=True, blank=True, verbose_name="终止时间")
    duration = models.IntegerField(null=False, verbose_name="授权周期（天）")

    add_time = models.DateTimeField(auto_now_add=True, verbose_name="记录添加时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="记录修改时间")

    status = models.BooleanField(default=False, verbose_name="认证是否被删除")
    is_expired = models.BooleanField(default=False, verbose_name="认证是否过期")

    cert_file = models.FileField(upload_to=cert_file_name, blank=True, null=True, verbose_name="手动认证文件",
                                 validators=[validate_file_extension])

    cert_code = models.CharField(max_length=512, blank=True, null=True, unique=True, verbose_name="手动认证信息")

    device = models.ForeignKey("DeviceInfo", on_delete=models.DO_NOTHING, null=False, blank=False,
                               related_name="certifications", verbose_name="设备")

    def save(self, *args, **kwargs):
        if self.start_time:
            self.end_time = self.start_time + datetime.timedelta(days=self.duration)

        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.device} 认证"

    def __repr__(self):
        return f"{self.device} 认证"

    class Meta:
        ordering = ["-add_time"]
        verbose_name = verbose_name_plural = "认证信息"